查看原文
其他

Unix昔日之魂(一):设计模式的历史探索

2016-09-23 翻译:刘甜甜 Gad-腾讯游戏开发者平台


2010年10月27日.本文由Neil Brown提供

对设计模式的探索是一次尤为重要的历史搜寻。目前很可能可以这么说,一种特定的情境设计或编码方式虽然能够在特定的情况下起作用,但从一个长期的或历史的角度来看,能够识别那些反复起作用的模式或者反复失败的模式才是必要的。我们总是得益于后见之明。

以往关于设计模式的系列文章都只是隐晦地涉及了Unix系统内核的发展历史,参照这些模式就可以发现,那个阶段的文章中很少有关于如何接近Unix系统内核的参考内容。通过参照长期多样化发展和努力的结果才能对未来有所展望,所有这些当然也包括一个数据库 。

在这一系列的文章中,我们试图寻找那些只在长期阶段中变得可视化的模式 。随着系统发展的不断前进,早期的一些决策可能在产生之初并不完全被人们所认同。如果我们能够找到联系这些决策和结果的模式,那么我们就有希望能在做出的新的决策时回顾这些模式,以帮助我们避免重犯老错误或者利用已经形成的成果。


完整开发

在此探索过程中,Ritchie Thompson 发表在ACM通讯上的论文正是一个非常有价值的起点,论文里介绍了“Unix 时间共享系统”。作者在论文里声明,“Unix系统的成功并不是一个新的发明,而是完整开发利用了一系列精挑细选的富有价值的理念。”而“精挑细选”的重要性则更像是暗示着一种有人曾建议过探索设计模式的历史性视角。只有在以往的经验可用时人们才能够做出选择,这也表明在此之中有大量的设计方法可供选择。人们所希望的是,能够在进行这些选择时注重模式的识别。

在未来四周内,我们将探讨能够追溯到Ritchie 和Thompson所写的早期Unix系统的四种模式,但这些模式以目前的视角完全可以看得更加清晰明了。遗憾的是,它们并不是全部都非常完美,但所有好的和坏的部分都可以为我们后续的设计提供经验教训的指导。

“完整开发”本质上也是一种模式,并且我们将会来回的重复进行探讨。无论是应用于软件开发,建筑,亦或是音乐创作,重复使用一个完美的理念都可以提高成果的完整性和凝聚力,并且非常有希望的是,这种模式在未来不需要进一步的证明辩护。这意味着,“完整开发”模式会受益于详尽的阐述,由此我们会得到这样的启发,至于其他三种模式,以下会通过对两个具体的例子进行阐述。

Ritchie 和Thompson在他们的论文摘要中鉴定了几个他们认为值得注意的Unix系统的特征。这些特征中最前面的两个特征也是我们最先探讨的两个实例。用他们的话来说:

1一个由可卸载卷组成的分层文件系统


2兼容文件、设备和I / O输入输出进程系统



文件描述符

其次来说,有时候这些文件描述符会被看作是Unix系统的关键性标志,并且会被人们改述成“所有的一切都是文件”。然而,这种理念有失公允,因为它夸大了实际情况。显然,并不是所有的都是文件。有些是设备,有些是通道,虽然它们中有一部分与文件具有共性的特征,但它们诚然不是文件。更准确的说,尽管它们不太引人注目,而特征描述将意味着“一切事物都会有一个文件描述符与之匹配”。文件描述符作为一个统一的概念,对设计来说是至关重要的。也正是文件描述符使得文件、设备和I/O输入输出进程系统能够实现互相兼容。

虽然文件、设备和通道是具有明显不同行为的不同物体,但它们仍然有相同的表现,并且通过使用相同的引用控制的进行读取,而这些相似之处恰好可以被我们利用。一个程序或库存程序并不关心差异性,也完全不需要了解这些差异,而且一个程序对这些差异的了解只需要知道与这些差异相关的特定的地方即可。

同样,在串行设备、磁带设备、磁盘设备、通道等等中采取并使用文件描述符的概念时,Unix系统获得了完整性,这已经被证明具有永久价值。在如今的 Linux系统中,我们也有网络接口的文件描述符,用于接收计时器事件和其他事件,并访问一系列在Unix系统被开发之初就已经想到的新设备。这种能够跟上时代日益发展变化的能力证明了文件描述符的强大力量,并表明这种能力对于完整开发模式的价值来说也是至关重要的。

正如我们将会看到的,无论是在开发初期还是在持续发展的过程中,文件描述符的概念并没有按它本该可以的程度,被尽可能的完整开发利用。我们将会发现的一些缺憾在于,我们是在文件描述符的完整开发过程中或者与之相关的理念中与机会擦肩而过,而且最多的优势在于文件描述符可以被用来激活新的功能。


单一、分层的命名空间

另一个值得注意的由Ritchie Thompson发现的特征(在他们的清单上位列第一 )是一个与一个由可卸载卷组成的分层文件系统

这里有目前关于这个系统尤其重要的三个方面的阐述。

1它是分层的。我们如今已非常习惯于分层的命名空间,这似乎是被给定的。然而,有时候它也是有点儿创新性的。一些同时期的文件系统,例如在CP / M中所使用的系统是没有子目录的。别的一些系统可能具备一个固定数量的分层水平,其中典型的是两层。
2它允许可拆卸卷。每一个不相同的存储卷可以存储一个相互分隔的分层系列文件集,而这种分隔在把所有文件打包成一个包罗万象的层级中被隐藏了。因此,分层命名的理念不仅仅是在单一的设备中有所使用,在包含所有存储设备的中也有所应用。
3它包含特定设备文件。这些文件是提供接入设备,包括调制解调器设备、字符设备和块设备、磁盘驱动器等的文件系统对象。因此,分层命名方案不仅包括文件和目录,也包括所有的设备。


在此所说的被完整开发的设计理念是分层命名空间。在单一存储设备,以及包括所有的存储设备中利用该理念的结果,并为设备以及存储设备提供访问路径的是一个“单一命名空间”。这提供了一个统一的命名方案,能够为在Unix系统中所运行的各种对象提供访问路径。

在随后的持续开发过程中,最突出的部分是虚拟文件系统,例如Linux系统中的进程文件系统( procfs )和系统文件系统( sysfs)。这些系统允许过程,并且允许其他诸多没有严格设备或者文件的实体出现在同一命名空间。

另一个有效的开发成果是允许其他对象出现在命名空间中的各种自动挂载或者自动安装启用中,这些也不一定都是存储设备。有两个例子,一是允许当地的主机连接入命名空间的 /net/hostname,二是允许用户名出现的/home/username。尽管它们没有使得主机和用户处于一级命名空间,但这仍然是具有价值的步骤。特别的,后者删除了对大多数壳和编辑所支持的波浪号前缀的需要(即,映射~用户名到该用户的主目录)。通过直接将此特征和命名空间合并,这个功能将会对所有程序可用。

对于文件描述符来说,分层命名空间的概念并没有按它本可以的程度被完整开发,因此我们实际上并没有一个单一的命名空间。造成这种没有完整开发的一些原因是在上文中已经被纠正过的“单纯的遗漏错失”。然而,由于分层命名空间是分离区域的存在,造成了至今仍然没有完全解决这个问题的不妙后果。命名空间就是命名空间设备,设备特定文件用于包括使设备接入单一命名空间,但是在某种程度上来说,无法完美实现高效率是一个缺陷。

一个小的映射会表明在UNIX系统中设备命名空间是一个有三层或者更多层的分层次空间。最高层区分开了“块设备”和“字符设备”。第二层在主设备上进行了编码,通常标识着该管理设备的驱动程序。在此之下是个一或两层的小数位字段编码。一个磁盘驱动器控制器可能使用一些字节来识别驱动,其他部分识别该驱动器的分区。串行设备驱动程序可能会确定一个特定的控制器,然后这几个控制器上的端口对应于一个特定的装置。

在UNIX系统中的设备特定文件只提供对该命名空间的有限访问权限。这有助于把它们视为接入这个备用命名空间的符号链接,能够提供一些额外的权限检查。然而,尽管符号链接可以点击进入在该分层的任何连接点,但是设备特定文件只能指向于实际对应的设备, 因此它们无法提供对该命名空间结构的访问路径。检查命名空间里的不同层级是不可能的,也无法在分层的特定节点中得到一个所有入口“目录清单”。

Linux系统开发人员已经多次尝试并试图通过诸多举措来纠正这种遗漏,比如devfs, devpts, udev, sysfs, 以及最近关注度更高的 devtmpfs。就这些各类尝试而言,纠正这种遗漏显然是一个巨大的难题。一部分困难源自于借助原始Unix系统的方式并使用所给的设备特定文件去保持向后兼容性,例如,稳定的权限设置。毫无疑问,同时也存在其他的困难。

不仅仅是设备层次不完全开放,而且也无法进行充分扩展。原先的对于255个主数字和255小数字的限制长期以来就不断延伸着这种痛苦。然而,顶层的“块或者字符设备”的区别则更加根深蒂固,并且难以改变。当网络设备发展一路走来,它们并没有真正的与“块设备”或者“字符设备”相适应,它们也并没有被压缩成为彼此不合适的模型,而是网络设备找到了拥有自己独立功能的独立命名空间,具有枚举所有设备,打开设备,重命名设备的功能。

所以当分层命名空间在早期设计阶段的开发利用中,它们并没有被完整开发,这导致在以后扩展中也无法继续的进行充分开发。


关闭

这两个例子——文件描述符和统一的分层命名空间,说明“完整开发”模式能够成为创建一个强大设计的非常有效的工具。尽管存在没有什么是能被完美执行的这种后见之明,但是这两个例子都对Unix系统和它的继任者增加了巨大的价值,也充分证明了这种模式的价值。当一个人无论何时在探索如何增加功能性时,对“如何在已经存在的基础上建立而不是一切重头开始创造”进行发问是非常重要的,并且询问“我们如何确信在现在能够建立,并且在未来也能够建立”也是同等重要的。

在本系列的下一篇文章里我们将探讨另外两个实例,考察它们的历史发展,并且引用一种不同的模式——一个会带来劣势而不是优势的模式。这种模式能够在早期就被识别,但仍然是一个容易粗心陷落的陷阱。

练习

有兴趣的读者可以尝试进行以下练习,进一步探讨一些在这篇文章中所提出的观点。这些都还没有确切的答案,但是,或许正是从问题开始能够牵引出有趣的发现。

1列出所有能够通过使用文件描述符可以被参考的内核对象和能够通过该文件描述符可以被施以影响的行为。做另一个不使用文件描述符的行为或对象列表,解释这样的行为或对象如何在被纳入文件描述符的完整开发过程中有所受益。
2在Unix系统或Linux系统中确定三个不同的命名空间,也不需要特意通过单一命名空间。对每一个命名空间确定其能够把命名空间合并成单一命名空间的好处。
3确定一个IP协议区域,看其在完整开发模式下是否已经产生重大简化或者其他效益。
4确定一个在 NFSv2协议中完整开发的设计元素。并对NFSv3 与NFSv4进行对比和比较。


 【版权声明】

原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权


点击一下立即阅读相关好文章


设计师如何避免沦为美工MMORPG游戏开始衰落了?


让人惊艳的黑科技程序员跨界还可以做什么


这么做设计才好玩守望先锋为什么好玩


人民币玩家一样会被吊打


......


近期热文

网络物理模拟(三):具有确定性的帧同步(上篇)

网络物理模拟(三):具有确定性的帧同步(下篇)



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存